package com.moleq.network;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class RemoteReportHandler extends Thread {

	private ReportCallback mCallback = null;
	private InetSocketAddress isa;
	private Socket clientSocket;
	private DataInputStream clientIn = null;
	private DataOutputStream clientOut = null;

	@Override
	public synchronized void start() {
		// TODO Auto-generated method stub

		bSwitch = true;

		super.start();
	}

	private ServerSocket sSocket = null;
	private boolean bSwitch = false;
	private ReportCreator mReportCreator;

	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();

		while (bSwitch) {
			try {
				sSocket = new ServerSocket(Constant.REMOTE_REPORT_PORT);
				System.out.println("Remote report Service Started...");
				while (!sSocket.isClosed() && null != sSocket) {
					Socket socket = sSocket.accept();

					new RemoteReportReader(socket).start();

				}
			} catch (Exception e) {
				e.printStackTrace();
			}

		}

	}

	public class RemoteReportReader extends Thread {

		private Socket socket = null;
		private DataInputStream dis = null;
		private DataOutputStream dos = null;

		public RemoteReportReader(Socket socket) {
			this.socket = socket;
			try {
				System.out.println("Remote client(" + socket.getInetAddress() + ") connected ");
				dis = new DataInputStream(socket.getInputStream());
				dos = new DataOutputStream(socket.getOutputStream());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();

			try {

				String reportData = "";
				String command = dis.readUTF();
				if (command == null)
					return;

				String[] pkg = command.split("\\|");

				if (pkg != null && pkg.length != 4)
					return;
				String action = pkg[0];
				String rptName = pkg[1];
				String fromDate = pkg[2];
				String toDate = pkg[3];

				if (action.equals(Constant.GET)) {
					if (mReportCreator != null) {
						reportData = mReportCreator.generateReport(rptName, fromDate, toDate);
					}

					dos.writeUTF(reportData);
					dos.flush();
				}

				Thread.sleep(800);
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			} finally {
				try {
					if (dis != null)
						dis.close();
					if (dos != null)
						dos.close();
					if (socket != null)
						socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	public void accessReport(String... args) {

		final String terminalIp = args[0];
		String reportName = args[1];
		String fromDate = args[2];
		String toDate = args[3];

		try {
			clientSocket = new Socket();
			isa = new InetSocketAddress(terminalIp, Constant.REMOTE_REPORT_PORT);
			clientSocket.connect(isa,500);

			if (clientSocket.isConnected()) {

				InputStream input = clientSocket.getInputStream();
				OutputStream output = clientSocket.getOutputStream();
				clientIn = new DataInputStream(new BufferedInputStream(input));
				clientOut = new DataOutputStream(new BufferedOutputStream(output));

				// clientIn = new
				// DataInputStream(clientSocket.getInputStream());
				// clientOut = new
				// DataOutputStream(clientSocket.getOutputStream());

				String cmmFormat = "%s|%s|%s|%s";
				String getCommand = String.format(cmmFormat, Constant.GET, reportName, fromDate, toDate);
				clientOut.writeUTF(getCommand);
				clientOut.flush();

				String reportData = clientIn.readUTF();

				if (reportData != null) {
					if (mCallback != null)
						mCallback.onCreate(reportData);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			if (mCallback != null)
				mCallback.onFaild(e.getMessage());
		} finally {
			try {
				if (clientIn != null) {
					clientIn.close();
				}
				if (clientOut != null) {
					clientOut.close();
				}
				if (clientSocket != null) {
					clientSocket.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
				if (mCallback != null)
					mCallback.onFaild(e.getMessage());
			}
		}
	}

	public void release() {
		try {
			bSwitch = false;
			if (null != sSocket)
				sSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void setReportCreator(ReportCreator creator, ReportCallback callback) {
		this.mCallback = callback;
		this.mReportCreator = creator;

	}

}
